package handler

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/olivere/elastic/v7"
	"goods_srv/global"
	"goods_srv/goodsPb"
	"goods_srv/model"
	"gorm.io/gorm"
)

type GoodsService struct {
	goods_pb.UnimplementedGoodsServer
}

func ModelToResponse(goods model.Goods) goods_pb.GoodsInfoResponse {
	goodsInfoResponse := goods_pb.GoodsInfoResponse{
		Id:              goods.ID,
		CategoryId:      goods.CategoryID,
		Name:            goods.Name,
		GoodsSn:         goods.GoodsSn,
		ClickNum:        goods.ClickNum,
		SoldNum:         goods.SoldNum,
		FavNum:          goods.FavNum,
		MarketPrice:     goods.MarketPrice,
		ShopPrice:       goods.ShopPrice,
		GoodsBrief:      goods.GoodsBrief,
		ShipFree:        goods.ShipFree,
		Images:          goods.Images,
		DescImages:      goods.DescImages,
		GoodsFrontImage: goods.GoodsFrontImage,
		IsNew:           goods.IsNew,
		IsHot:           goods.IsHot,
		OnSale:          goods.OnSale,
		Category: &goods_pb.CategoryBriefInfoResponse{
			Id:   goods.Category.ID,
			Name: goods.Category.Name,
		},
		Brand: &goods_pb.BrandInfoResponse{
			Id:   goods.Brands.ID,
			Name: goods.Brands.Name,
			Logo: goods.Brands.Logo,
		},
	}
	return goodsInfoResponse
}

// 商品列表
func (g *GoodsService) GoodsList(ctx context.Context, in *goods_pb.GoodsFilterRequest) (*goods_pb.GoodsListResponse, error) {
	goodsListResponse := &goods_pb.GoodsListResponse{}

	var goods []model.Goods

	//match bool 复合查询
	q := elastic.NewBoolQuery()
	//链式操作
	localDb := global.DB.Model(model.Goods{})

	//是否是关键词
	if in.KeyWords != "" {
		//搜索
		localDb = localDb.Where("name LIKE ?", "%"+in.KeyWords+"%")
		q = q.Must(elastic.NewMultiMatchQuery(in.KeyWords, "name", "goods_brief"))
	}

	//是否是热卖商品
	if in.IsHot {
		localDb = localDb.Where(model.Goods{IsHot: true})
		q = q.Filter(elastic.NewTermQuery("is_hot", in.IsHot))
	}

	//是否是新品商品
	if in.IsNew {
		localDb = localDb.Where(model.Goods{IsNew: true})
		q = q.Filter(elastic.NewTermQuery("is_new", in.IsNew))
	}

	//商品最低价格
	if in.PriceMin > 0 {
		localDb = localDb.Where("shop_price>=?", in.PriceMin)
		q = q.Filter(elastic.NewRangeQuery("shop_price").Gte(in.PriceMin))
	}

	//商品最高价格
	if in.PriceMax > 0 {
		localDb = localDb.Where("shop_price<=?", in.PriceMax)
		q = q.Filter(elastic.NewRangeQuery("shop_price").Lte(in.PriceMax))
	}

	//品牌条件筛选
	if in.Brand > 0 {
		localDb = localDb.Where("brands_id = ?", in.Brand)
		q = q.Filter(elastic.NewTermQuery("brands_id", in.Brand))
	}

	//通过cateGory去查询商品
	var subQuery string
	if in.TopCategory > 0 {
		var category model.Category

		res := global.DB.Model(model.Category{}).Limit(1).Find(&category)
		if res.RowsAffected == 0 {
			return nil, errors.New("商品分类不存在")
		}
		if category.Level == 1 {
			subQuery = fmt.Sprintf("select id from category where parent_category_id in (select id from category WHERE parent_category_id=%d)", in.TopCategory)
		} else if category.Level == 2 {
			subQuery = fmt.Sprintf("select id from category WHERE parent_category_id=%d", in.TopCategory)
		} else if category.Level == 3 {
			subQuery = fmt.Sprintf("select id from category WHERE id=%d", in.TopCategory)
		}
		localDb = localDb.Where(fmt.Sprintf("category_id in (%s)", subQuery))
	}
	//es搜索
	switch {
	case in.PagePerNums > 100:
		in.PagePerNums = 100
	case in.PagePerNums <= 0:
		in.PagePerNums = 10
	}

	res, err := global.EsClient.Search().
		Index(model.EsGoods{}.GetIndexName()). // search in index "twitter"
		Query(q).                              // specify the query
		From(int(in.Pages * in.PagePerNums)).Size(int(in.PagePerNums)).
		Do(ctx) // execute
	if err != nil {
		// Handle error
		panic(err)
	}

	var goodsIds []int32

	if res.Hits.TotalHits.Value > 0 {
		for _, hit := range res.Hits.Hits {
			goods := model.EsGoods{}
			json.Unmarshal(hit.Source, &goods)
			goodsIds = append(goodsIds, goods.ID)
		}
	}

	//查询id在某个数组中的值
	//select * from goods join category on category.id=goods.category_id join brands on nrands.id=goods.Brands_id where goods.id in ()
	re := localDb.Preload("Category").Preload("Brands").Find(&goods, goodsIds)
	if re.Error != nil {
		return nil, re.Error
	}

	for _, good := range goods {
		goodsInfoResponse := ModelToResponse(good)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfoResponse)
	}

	return goodsListResponse, nil
}

// 页码
func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page == 0 {
			page = 1
		}

		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}
		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

// 添加商品
func (g *GoodsService) CreateGoods(ctx context.Context, in *goods_pb.CreateGoodsInfo) (*goods_pb.GoodsInfoResponse, error) {
	//查看分类是否存在
	category, err := model.GetCategory(in.CategoryId)
	if err != nil {
		return nil, err
	}
	//查看品牌是否存在
	brand, err := model.GetBrand(in.BrandId)
	if err != nil {
		return nil, err
	}
	//添加商品
	goods := model.Goods{
		CategoryID:      category.ID,
		Category:        *category,
		BrandsID:        brand.ID,
		Brands:          *brand,
		OnSale:          in.OnSale,
		ShipFree:        in.ShipFree,
		IsNew:           in.IsNew,
		IsHot:           in.IsHot,
		Name:            in.Name,
		GoodsSn:         in.GoodsSn,
		MarketPrice:     in.MarketPrice,
		ShopPrice:       in.ShopPrice,
		GoodsBrief:      in.GoodsBrief,
		Images:          in.Images,
		DescImages:      in.DescImages,
		GoodsFrontImage: in.GoodsFrontImage,
	}
	err = goods.AddGoods()
	if err != nil {
		return nil, err
	}
	goodsInfoResponse := ModelToResponse(goods)
	return &goodsInfoResponse, nil
}

// 更新商品信息
func (g *GoodsService) UpdateGoods(ctx context.Context, in *goods_pb.CreateGoodsInfo) (*goods_pb.Empty, error) {
	//查看分类是否存在
	category, err := model.GetCategory(in.CategoryId)
	if err != nil {
		return nil, err
	}
	//查看品牌是否存在
	brand, err := model.GetBrand(in.BrandId)
	if err != nil {
		return nil, err
	}
	//查看商品是否存在
	goods, err := model.GetGoods(in.Id)
	if err != nil {
		return nil, err
	}
	//更新商品
	goodsInfo := model.Goods{
		BaseModel: model.BaseModel{
			ID: goods.ID,
		},
		CategoryID:      category.ID,
		Category:        *category,
		BrandsID:        brand.ID,
		Brands:          *brand,
		OnSale:          in.OnSale,
		ShipFree:        in.ShipFree,
		IsNew:           in.IsNew,
		IsHot:           in.IsHot,
		Name:            in.Name,
		GoodsSn:         in.GoodsSn,
		MarketPrice:     in.MarketPrice,
		ShopPrice:       in.ShopPrice,
		GoodsBrief:      in.GoodsBrief,
		Images:          in.Images,
		DescImages:      in.DescImages,
		GoodsFrontImage: in.GoodsFrontImage,
	}
	err = goodsInfo.UpdateGoods()
	if err != nil {
		return nil, err
	}
	return &goods_pb.Empty{}, nil
}

// 商品详情
func (g *GoodsService) GetGoodsDetail(ctx context.Context, in *goods_pb.GoodInfoRequest) (*goods_pb.GoodsInfoResponse, error) {
	goods, err := model.GetGoods(in.Id)
	if err != nil {
		return nil, err
	}
	goodsinfo := ModelToResponse(*goods)
	return &goodsinfo, nil
}

//// 删除商品
//func (g *GoodsService) DeleteGoods(ctx context.Context, in *goods_pb.DeleteGoodsRequest) (*goods_pb.Empty, error) {
//	_, err := model.DeleteGoods(in.Id)
//	if err != nil {
//		return nil, err
//	}
//	return &goods_pb.Empty{}, nil
//}

// 根据id批量获取商品数据
func (g *GoodsService) BatchGetGoods(ctx context.Context, in *goods_pb.BatchGoodsIdInfo) (*goods_pb.GoodsListResponse, error) {
	goodsListResponse := goods_pb.GoodsListResponse{}

	var goods []model.Goods

	res := global.DB.Preload("Category").Preload("Brands").Where("id in (?)", in.Id).Find(&goods)
	if res.Error != nil {
		return nil, res.Error
	}
	for _, v := range goods {
		goodsInfo := ModelToResponse(v)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfo)
	}
	return &goodsListResponse, nil
}
